home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / 3D graphics ƒ / g3D_EvalFunc.c < prev    next >
Text File  |  1989-08-28  |  14KB  |  788 lines

  1. /*
  2.     Copyright '89    Christopher Moll
  3.     all rights reserved
  4. */
  5.  
  6.  
  7. #include    "graph3D.h"
  8. #include    <math.h>
  9. #include    <ctype.h>
  10. #ifndef    _LSC3_
  11. #    include    <QuickDraw.h>
  12. #    include    <TextEdit.h>
  13. #    include    <EventMgr.h>
  14. #    include    <DialogMgr.h>
  15. #    include    <MemoryMgr.h>
  16. #endif
  17.  
  18.  
  19. extern    DialogPtr        functDial;
  20.  
  21. extern    Boolean    useMainFunc;
  22.  
  23. extern    int        mainFunct[64];
  24. extern    int        numMnOps;
  25. extern    Real    mnConsts[30];
  26. extern    int        numMnConsts;
  27.  
  28. extern    int        derivFunct[64];
  29. extern    int        numDerivOps;
  30. extern    Real    derivConsts[30];
  31. extern    int        numDerivConsts;
  32.  
  33. extern    Real        *funcResults;
  34. extern    Vector        *scalVectResults;
  35. extern    Point        *graphPoints;    /* same elements as funcResults */
  36.  
  37. extern    Real    startX, startY;
  38. extern    Real    endX, endY;
  39. extern    Real    deltaX, deltaY;
  40. extern    int        numX, numY;
  41.  
  42. extern    Boolean        functCurrent;
  43. extern    Boolean        vectrsCurrent;
  44.  
  45. extern    Boolean        noRedrawGrph;
  46.  
  47. extern    int            graphType;
  48.  
  49. extern    Vector        maxVect, minVect;
  50.  
  51. extern    Real        rotMatrx[3][3];
  52. extern    Boolean        inMultiFndr;
  53.  
  54. /***        Local to this file        ***/
  55. Real    startX, startY;
  56. Real    endX, endY;
  57. Real    deltaX, deltaY;
  58. int        numX, numY;
  59.  
  60.  
  61. Boolean        invldFormla;
  62. static    int        *texasPtr;
  63.  
  64.  
  65. static    int lastOp = END_OP;
  66.  
  67.  
  68. EvalFunction()
  69. {
  70.     Boolean    AllocatePts();
  71.  
  72.     invldFormla = FALSE;
  73.     noRedrawGrph = TRUE;
  74.  
  75.     if (graphType EQ FUNCT_GTYPE)
  76.         LoadFunction();
  77.     else
  78.         LoadDeriv();
  79.  
  80.     if (invldFormla)    /* already gave warning message */
  81.         return;
  82.  
  83.     GetSpecDCont();
  84.  
  85.     deltaX = (endX - startX) / (numX - 1);
  86.     deltaY = (endY - startY) / (numY - 1);
  87.  
  88.     if (NOT(AllocatePts()))
  89.     {
  90.         MemAlert();
  91.         return;
  92.     }
  93.  
  94.     if (graphType EQ FUNCT_GTYPE)
  95.         StoreFunction();
  96.     else
  97.         StoreDeriv();
  98.  
  99.     vectrsCurrent = FALSE;
  100.     functCurrent = TRUE;
  101.     noRedrawGrph = FALSE;
  102. }
  103.  
  104.  
  105. LoadFunction()
  106. {
  107.     char    contStr[256];
  108.     int        itemType;
  109.     Handle    itemHndle;
  110.     Rect    itemRect;
  111.  
  112.     useMainFunc = TRUE;
  113.     GetDItem(functDial, DIALI_F_FUNCT, &itemType, &itemHndle, &itemRect);
  114.     GetIText(itemHndle, contStr);
  115.     ptoc(contStr);
  116.     ReadFormula(contStr);
  117. }
  118.  
  119. static
  120. ReadFormula(argStr)
  121. char    *argStr;
  122. {
  123.     int    op, lenOp;
  124.     Boolean    done = FALSE;
  125.     char    *strPtr;
  126.     int        lenStr;
  127.     int        texas[50];
  128.  
  129.     ToUprStr(argStr);
  130.     if (useMainFunc)
  131.     {
  132.         numMnOps = 0;
  133.         numMnConsts = 0;
  134.     }
  135.     else
  136.     {
  137.         numDerivOps = 0;
  138.         numDerivConsts = 0;
  139.     }
  140.  
  141.     texasPtr = texas + 49;
  142.     *texasPtr = END_SYMB;
  143.  
  144.     lenStr = strlen(argStr);
  145.     strPtr = argStr;
  146.  
  147.     invldFormla = FALSE;
  148.     lastOp = END_OP;
  149.  
  150.     while (NOT(done))
  151.     {
  152.         while(isspace(*strPtr))
  153.             ++strPtr;
  154.  
  155.         if (strPtr - argStr EQ lenStr)
  156.         {
  157.             op = END_SYMB;
  158.             lenOp = 0;
  159.         }
  160.         else
  161.             NextOp(strPtr, &op, &lenOp);
  162.         DoAction(op, lenOp, &done, &strPtr);
  163.     }
  164.     if (invldFormla)
  165.     {
  166.         Alert(ALRT_FORM, NIL);
  167.         if (useMainFunc)
  168.             numMnOps = 0;
  169.         else
  170.             numDerivOps = 0;
  171.     }
  172. }
  173.  
  174. ToUprStr(str)
  175. register    unsigned char    *str;
  176. {
  177. register    unsigned char c;
  178.  
  179.     c = *str;
  180.     while (c)
  181.     {
  182.         if ((*str >= 'a') AND (*str <= 'z'))
  183.             *str -= 'a' - 'A';
  184.         c = *(++str);
  185.     }
  186. }
  187.  
  188. static
  189. NextOp(argStr, op, lenOp)
  190. char    *argStr;
  191. int    *op, *lenOp;
  192. {
  193.     int    FindFunc(), LenNum();
  194.  
  195.     *lenOp = 1;
  196.     if (isdigit(argStr[0]) OR (argStr[0] EQ '.'))
  197.     {
  198.         *op = PUSH_NUM_OP;
  199.         *lenOp = LenNum(argStr);
  200.         return;
  201.     }
  202.  
  203.     switch (argStr[0]) {
  204.     case 'X':
  205.         *op = PUSH_X_OP;
  206.         break;
  207.     case 'Y':
  208.         *op = PUSH_Y_OP;
  209.         break;
  210.     case 'Z':
  211.         if (graphType EQ DERIV_GTYPE)
  212.             *op = PUSH_Z_OP;
  213.         else
  214.             invldFormla = TRUE;
  215.         break;
  216.     case 'R':
  217.         if (graphType EQ CYLIND_GTYPE)
  218.             *op = PUSH_X_OP;
  219.         else
  220.             invldFormla = TRUE;
  221.         break;
  222.     case 'P':
  223.         if (graphType EQ CYLIND_GTYPE)
  224.             *op = PUSH_Y_OP;
  225.         else
  226.             invldFormla = TRUE;
  227.         break;
  228.     case '+':
  229.         *op = ADD_OP;
  230.         break;
  231.     case '-':
  232.         *op = SUBT_OP;
  233.         break;
  234.     case '*':
  235.         *op = MULT_OP;
  236.         break;
  237.     case '/':
  238.         *op = DIV_OP;
  239.         break;
  240.     case '^':
  241.         *op = POWER_OP;
  242.         break;
  243.     case '(':
  244.         *op = OP_L_PAREN;
  245.         break;
  246.     case ')':
  247.         *op = OP_R_PAREN;
  248.         break;
  249.     default:
  250.         *op = FindFunc(argStr, lenOp);
  251.     }
  252. }
  253.  
  254. static
  255. int
  256. FindFunc(funcStr, lenFunc)
  257. register    char    *funcStr;
  258. int            *lenFunc;
  259. {
  260.     if (NOT(strncmp(funcStr, "EXP", 3))) {
  261.         *lenFunc = 3;
  262.         return(EXP_OP);
  263.     }
  264.     if (NOT(strncmp(funcStr, "LOG", 3))) {
  265.         *lenFunc = 3;
  266.         return(LOG_OP);
  267.     }
  268.     if (NOT(strncmp(funcStr, "LOG10", 5))) {
  269.         *lenFunc = 5;
  270.         return(LOG10_OP);
  271.     }
  272.     if (NOT(strncmp(funcStr, "SQRT", 4))) {
  273.         *lenFunc = 4;
  274.         return(SQRT_OP);
  275.     }
  276.     if (NOT(strncmp(funcStr, "SQ", 2))) {
  277.         *lenFunc = 2;
  278.         return(SQ_OP);
  279.     }
  280.     if (NOT(strncmp(funcStr, "SINH", 4))) {
  281.         *lenFunc = 4;
  282.         return(SINH_OP);
  283.     }
  284.     if (NOT(strncmp(funcStr, "COSH", 4))) {
  285.         *lenFunc = 4;
  286.         return(COSH_OP);
  287.     }
  288.     if (NOT(strncmp(funcStr, "TANH", 4))) {
  289.         *lenFunc = 4;
  290.         return(TANH_OP);
  291.     }
  292.     if (NOT(strncmp(funcStr, "SIN", 3))) {
  293.         *lenFunc = 3;
  294.         return(SIN_OP);
  295.     }
  296.     if (NOT(strncmp(funcStr, "ASIN", 4))) {
  297.         *lenFunc = 4;
  298.         return(ASIN_OP);
  299.     }
  300.     if (NOT(strncmp(funcStr, "COS", 3))) {
  301.         *lenFunc = 3;
  302.         return(COS_OP);
  303.     }
  304.     if (NOT(strncmp(funcStr, "ACOS", 4))) {
  305.         *lenFunc = 4;
  306.         return(ACOS_OP);
  307.     }
  308.     if (NOT(strncmp(funcStr, "TAN", 3))) {
  309.         *lenFunc = 3;
  310.         return(TAN_OP);
  311.     }
  312.     if (NOT(strncmp(funcStr, "ATAN", 4))) {
  313.         *lenFunc = 4;
  314.         return(ATAN_OP);
  315.     }
  316.     if (NOT(strncmp(funcStr, "COTAN", 5))) {
  317.         *lenFunc = 5;
  318.         return(COTAN_OP);
  319.     }
  320.     invldFormla = TRUE;
  321. }
  322.  
  323. static
  324. int
  325. LenNum(argStr)
  326. register    char    *argStr;
  327. {
  328. register    char    *tstr;
  329.  
  330.     tstr = argStr;
  331.  
  332.     while(isdigit(*tstr))
  333.         ++tstr;
  334.  
  335.     if (*tstr EQ '.')
  336.     {
  337.         ++tstr;
  338.         while(isdigit(*tstr))
  339.             ++tstr;
  340.     }
  341.  
  342.     if ((*tstr EQ 'e') OR (*tstr EQ 'E'))
  343.     {
  344.         ++tstr;
  345.         if ((*tstr = '+') OR (*tstr = '-'))
  346.             ++tstr;
  347.         while(isdigit(*tstr))
  348.             ++tstr;
  349.     }
  350.     return((int)(tstr - argStr));
  351. }
  352.  
  353.  
  354. #define    CMP_NONE    0
  355. #define    CMP_SIGN    1
  356. #define    CMP_HALT    2
  357. #define    CMP_ERROR    3
  358.  
  359.  
  360. static
  361. DoAction(op, lenOp, done, argStr)
  362. int        op;
  363. int        lenOp;
  364. Boolean *done;
  365. char    **argStr;
  366. {
  367.     int        action, localOp;
  368.     Boolean    popOp;
  369.     int        CheckSymbs();
  370.  
  371.     localOp = op;
  372.  
  373.     action = CheckSymbs(&localOp, done);
  374.  
  375.     switch (action) {
  376.     case ACT_OPtTEX:    /* send it to texas */
  377.         --texasPtr;
  378.         *texasPtr = localOp;
  379.         popOp = TRUE;
  380.         break;
  381.     case ACT_TEXtF:        /* pop from texas to formula */
  382.         PushOpFormula(*texasPtr++);
  383.         popOp = FALSE;
  384.         break;
  385.     case ACT_DELOPT:    /* send it to texas */
  386.         ++texasPtr;
  387.         popOp = TRUE;
  388.         break;
  389.     case ACT_STPDN:        /* we're done */
  390.         *done = TRUE;
  391.         popOp = FALSE;
  392.         break;
  393.     case ACT_STPERR:    /* something wrong; stop */
  394.         invldFormla = TRUE;
  395.         *done = TRUE;
  396.         popOp = FALSE;
  397.         break;
  398.     case ACT_OPtF:    /* add it to the formula */
  399.         PushOpFormula(localOp);
  400.         popOp = TRUE;
  401.         if (localOp EQ PUSH_NUM_OP)
  402.             PushConst(*argStr);
  403.         break;
  404.     case ACT_DELOP:    /* get rid of it */
  405.         popOp = TRUE;
  406.         break;
  407.     }
  408.  
  409.     if (popOp)
  410.         *argStr += lenOp;
  411. }
  412.  
  413. static
  414. PushOpFormula(newOp)
  415. int    newOp;
  416. {
  417.     if (useMainFunc)
  418.     {
  419.         mainFunct[numMnOps] = newOp;
  420.         ++numMnOps;
  421. /*        if (numMnOps > MAX_OPS)
  422.             GeneralAlert("Formula too complex");
  423. */
  424.     }
  425.     else
  426.     {
  427.         derivFunct[numDerivOps] = newOp;
  428.         ++numDerivOps;
  429.     }
  430. }
  431.  
  432. static
  433. PushConst(constStr)
  434. char    *constStr;
  435. {
  436.     Real    atof();
  437.  
  438.     if (useMainFunc)
  439.         mnConsts[numMnConsts++] = atof(constStr);
  440.     else
  441.         derivConsts[numDerivConsts++] = atof(constStr);
  442. }
  443.  
  444. static
  445. int
  446. CheckSymbs(op, done)
  447. int        *op;
  448. Boolean    *done;
  449. {
  450.  
  451.  
  452. static    int        actionTable[MAX_SYMBS][MAX_SYMBS] = {
  453.                         /* next symb -> */
  454.         /* texas V */
  455.                         4,1,1,1,1,1,1,5,1,6,1,
  456.                         2,2,2,1,1,1,1,2,1,6,1,
  457.                         2,2,2,1,1,1,1,2,1,6,1,
  458.                         2,2,2,2,2,1,1,2,1,6,1,
  459.                         2,2,2,2,2,1,1,2,1,6,1,
  460.                         2,2,2,2,2,2,1,2,1,6,1,
  461.                         5,1,1,1,1,1,1,3,1,6,1,
  462.                         5,5,5,5,5,5,5,5,1,5,1,
  463.                         2,2,2,2,2,2,1,2,5,5,1,
  464.                         5,5,5,5,5,5,5,5,5,5,1,
  465.                         2,2,2,2,2,2,1,2,1,6,1
  466.                         };
  467.  
  468.  
  469. static    int        compareOps[MAX_SYMBS][MAX_SYMBS] = {
  470. /*curr op -> */
  471. /*last op V */
  472. CMP_HALT,  CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  473. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  474. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  475. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  476. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  477. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE/*CMP_ERROR*/, CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  478. CMP_ERROR, CMP_SIGN,  CMP_SIGN,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE,
  479. CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_ERROR, CMP_NONE,
  480. CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,
  481. CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_ERROR, CMP_NONE,
  482. CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_ERROR, CMP_NONE,  CMP_ERROR, CMP_NONE,  CMP_NONE,  CMP_NONE
  483. };
  484.  
  485.     int    errCode, symbol, action;
  486.  
  487.  
  488.     symbol = SymbFromOp(*op);
  489.  
  490.     action = actionTable[SymbFromOp(*texasPtr)][symbol];
  491.  
  492.     errCode = compareOps[SymbFromOp(lastOp)][SymbFromOp(*op)];
  493.  
  494.     switch (errCode) {
  495.     case CMP_NONE:
  496.         break;
  497.     case CMP_SIGN:
  498.         if (*op EQ SUBT_OP)
  499.             *op = NEG_OP;
  500.         else
  501.             action = ACT_DELOP;
  502.         action = actionTable[SymbFromOp(*texasPtr)][SymbFromOp(*op)];
  503.         break;
  504.     case CMP_HALT:
  505.         *done = TRUE;
  506.         break;
  507.     case CMP_ERROR:
  508.         *done = TRUE;
  509.         invldFormla = TRUE;
  510.         break;
  511.     default:
  512.         *done = TRUE;
  513.     }
  514.  
  515.     if ((action NEQ ACT_DELOP) AND (action NEQ ACT_TEXtF))
  516.         lastOp = *op;
  517.  
  518.     return(action);
  519. }
  520.  
  521. static
  522. int
  523. SymbFromOp(op)
  524. int    op;
  525. {
  526.     if (op < 0) {
  527.         if (op > OP_L_PAREN)
  528.             return(NUMB_SYMB);
  529.         if (op EQ OP_L_PAREN)
  530.             return(L_PAREN_SYMB);
  531.         return(R_PAREN_SYMB);
  532.     }
  533.  
  534.     if (op EQ END_OP)
  535.         return(END_SYMB);
  536.  
  537.     if (op <= POWER_OP)
  538.         return(op);
  539.  
  540.     if (op EQ NEG_OP)
  541.         return(NEG_SYMB);
  542.     else if (op > NEG_OP)
  543.         return(FUNC_SYMB);
  544.     
  545.     return(END_SYMB);
  546. }
  547.  
  548. static
  549. LoadDeriv()
  550. {
  551.     char    contStr[256];
  552.     int        itemType;
  553.     Handle    itemHndle;
  554.     Rect    itemRect;
  555.  
  556.     useMainFunc = TRUE;
  557.     GetDItem(functDial, DIALI_D_FUNC1, &itemType, &itemHndle, &itemRect);
  558.     GetIText(itemHndle, contStr);
  559.     ptoc(contStr);
  560.     ReadFormula(contStr);
  561.  
  562.     useMainFunc = FALSE;
  563.     GetDItem(functDial, DIALI_D_FUNC2, &itemType, &itemHndle, &itemRect);
  564.     GetIText(itemHndle, contStr);
  565.     ptoc(contStr);
  566.     ReadFormula(contStr);
  567. }
  568.  
  569. Boolean
  570. AllocatePts()
  571. {
  572.     if (funcResults NEQ NIL)
  573.         free(funcResults);
  574.     if (scalVectResults NEQ NIL)
  575.         free(scalVectResults);
  576.     if (graphPoints NEQ NIL)
  577.         free(graphPoints);
  578.     funcResults = (Real *)NewPtr((long)sizeof(Real) * (long)numX * numY);
  579.     if (MemErr)
  580.         goto Fail;
  581.     scalVectResults = (Vector *)NewPtr((long)sizeof(Vector) * (long)numX * numY);
  582.     if (MemErr)
  583.         goto Fail;
  584.     graphPoints = (Point *)NewPtr((long)sizeof(Point) * (long)numX * numY);
  585.     if (MemErr)
  586.         goto Fail;
  587.  
  588.     return(TRUE);
  589. Fail:
  590.     InitPts();
  591.     return(FALSE);
  592. }
  593.  
  594. MemAlert()
  595. {
  596.     InitCursor();
  597.     Alert(ALRT_MEMRY, NIL);
  598. }
  599.  
  600. static
  601. StoreFunction()
  602. {
  603.     register    int    xCnt, yCnt;
  604.     Real        currX, currY;
  605.     Real        maxFunc, minFunc, funcVal;
  606.     Real        xAtMax, yAtMax;
  607.     Real        xAtMin, yAtMin;
  608.     Real        TheFunction();
  609.     Boolean        CmndPeriod();
  610.     
  611.     ShowMeter((long)numX * numY);
  612.  
  613.     useMainFunc = TRUE;
  614.     funcVal = TheFunction(startX, startY);
  615.     maxFunc = funcVal;
  616.     minFunc = funcVal;
  617.     xAtMax = startX;
  618.     yAtMax = startY;
  619.     xAtMin = startX;
  620.     yAtMin = startY;
  621.  
  622.     currX = startX;
  623.     for (xCnt = 0; xCnt < numX; xCnt++)
  624.     {
  625.         currY = startY;
  626.         for (yCnt = 0; yCnt < numY; yCnt++)
  627.         {
  628.             funcVal = TheFunction(currX, currY);
  629.             DisplayMeter();
  630.             funcResults[(long)xCnt * (long)numY + yCnt] = funcVal;
  631.             if (funcVal > maxFunc)
  632.             {
  633.                 maxFunc = funcVal;
  634.                 xAtMax = currX;
  635.                 yAtMax = currY;
  636.             }
  637.             else if (funcVal < minFunc)
  638.             {
  639.                 minFunc = funcVal;
  640.                 xAtMin = currX;
  641.                 yAtMin = currY;
  642.             }
  643.             currY += deltaY;
  644.         }
  645.         if (CmndPeriod())
  646.             break;  /* for */
  647.         currX += deltaX;
  648.     }
  649.  
  650. done:
  651.     maxVect.x = xAtMax;
  652.     maxVect.y = yAtMax;
  653.     maxVect.z = maxFunc;
  654.     minVect.x = xAtMin;
  655.     minVect.y = yAtMin;
  656.     minVect.z = minFunc;
  657.  
  658.     RemoveMeter();
  659. }
  660.  
  661. static
  662. StoreDeriv()
  663. {
  664.     register    int    xCnt, yCnt;
  665.     Real        currFValX, currFValY;
  666.     Real        currX, currY, midXsqr, midYsqr;
  667.     Real        HlfDeltaX, HlfDeltaY;
  668.  
  669.     Real        maxFunc, minFunc;
  670.     Real        xAtMax, yAtMax;
  671.     Real        xAtMin, yAtMin;
  672.     Real        TheFunction(), GetInitVal();
  673.     Boolean        CmndPeriod();
  674.     
  675.     currFValX = GetInitVal();
  676.     ShowMeter((long)numX * numY);
  677.  
  678.     HlfDeltaX = deltaX / 2.0;
  679.     HlfDeltaY = deltaY / 2.0;
  680.  
  681.     maxFunc = currFValX;
  682.     minFunc = currFValX;
  683.     xAtMax = startX;
  684.     yAtMax = startY;
  685.     xAtMin = startX;
  686.     yAtMin = startY;
  687.  
  688.     currX = startX;
  689.     midXsqr = currX + HlfDeltaX;
  690.     for (xCnt = 0; xCnt < numX; xCnt++)
  691.     {
  692.         currFValY = currFValX;
  693.         currY = startY;
  694.         midYsqr = currY + HlfDeltaY;
  695.         useMainFunc = FALSE;    /* calculate dz/dy */
  696.         for (yCnt = 0; yCnt < numY; yCnt++)
  697.         {
  698.             DisplayMeter();
  699.             funcResults[xCnt * numY + yCnt] = currFValY;
  700.             if (currFValY > maxFunc)
  701.             {
  702.                 maxFunc = currFValY;
  703.                 xAtMax = currX;
  704.                 yAtMax = currY;
  705.             }
  706.             else if (currFValY < minFunc)
  707.             {
  708.                 minFunc = currFValY;
  709.                 xAtMin = currX;
  710.                 yAtMin = currY;
  711.             }
  712.             currFValY = currFValY +
  713.                     (TheFunction(currX, midYsqr, currFValY) * deltaY);
  714.             currY += deltaY;
  715.             midYsqr = currY + HlfDeltaY;
  716.         }
  717.         if (CmndPeriod())
  718.             break;  /* for */
  719.         useMainFunc = TRUE;    /* calculate dz/dx */
  720.         currFValX = currFValX +
  721.                     (TheFunction(midXsqr, startY, currFValX) * deltaX);
  722.         currX += deltaX;
  723.         midXsqr = currX + HlfDeltaX;
  724.     }
  725.  
  726.     maxVect.x = xAtMax;
  727.     maxVect.y = yAtMax;
  728.     maxVect.z = maxFunc;
  729.     minVect.x = xAtMin;
  730.     minVect.y = yAtMin;
  731.     minVect.z = minFunc;
  732.  
  733.     RemoveMeter();
  734. }
  735.  
  736. static
  737. Real
  738. GetInitVal()
  739. {
  740.     DialogRecord dStorage;
  741.     DialogPtr    initValDial;
  742.     int        itemSelected;
  743.     char    numStrX[100], numStrY[100];
  744.     Handle    itmHand, DialHandle();
  745.     double    atof();
  746. static    double    lastInitVal = 0.0;
  747.  
  748.     sprintf(numStrX, "%f", startX);
  749.     sprintf(numStrY, "%f", startY);
  750.     ctop(numStrX);
  751.     ctop(numStrY);
  752.     ParamText(numStrX, numStrY, "", "");
  753.  
  754.     initValDial = GetNewDialog(DIAL_INITVL, &dStorage, -1L);
  755.     itmHand = DialHandle(initValDial, DIALI_I_VALUE);
  756.     sprintf(numStrX, "%f", lastInitVal);
  757.     ctop(numStrX);
  758.     SetIText(itmHand, numStrX);
  759.  
  760.     ShowWindow(initValDial);
  761.  
  762.     InitCursor();
  763.     do {
  764.         ModalDialog(NIL, &itemSelected);
  765.     } while (itemSelected NEQ OK);
  766.     Clock();
  767.  
  768.     GetIText(itmHand, numStrX);
  769.     ptoc(numStrX);
  770.     CloseDialog(initValDial);
  771.  
  772.     lastInitVal = atof(numStrX);
  773.     return(lastInitVal);
  774. }
  775.  
  776. Handle
  777. DialHandle(theDial, theItem)
  778. DialogPtr    theDial;
  779. int        theItem;
  780. {
  781.     int        itemTyp;
  782.     Handle    itmHand;
  783.     Rect    disp;
  784.  
  785.     GetDItem(theDial, theItem, &itemTyp, &itmHand, &disp);
  786.     return(itmHand);
  787. }
  788.